"""
Created on 2024-08-21
@author:LiuFei
@description: 数据表设计

"""
# from django.contrib.auth import get_user_model
from django.db import models
from django.utils.translation import gettext as _
from django.conf import settings
from yc_django_utils.models import BaseModel
from simple_history.models import HistoricalRecords
from treebeard.mp_tree import MP_Node

# User = get_user_model()

table_prefix = settings.TABLE_PREFIX


class Role(BaseModel):
    """
    角色表
    """
    name = models.CharField(max_length=50, verbose_name=_('角色名称'))
    description = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('角色描述'))
    key = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('角色标识'))
    status = models.BooleanField(default=True, verbose_name=_('状态'))
    sort = models.IntegerField(default=1, verbose_name=_('排序'))
    # user = models.ManyToManyField(User, related_name='roles', verbose_name=_('用户'), db_constraint=False)
    history = HistoricalRecords(verbose_name=_("历史修改记录"))

    def __str__(self):
        return self.name

    class Meta:
        db_table = f'{table_prefix}_role'
        verbose_name = _('角色管理')
        verbose_name_plural = verbose_name
        ordering = ['-id']


class Post(BaseModel):
    """
    岗位表
    """
    STATUS_CHOICES = (
        (0, _('在职')),
        (1, _('离职')),
    )
    name = models.CharField(max_length=64, verbose_name=_('岗位名称'))
    code = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('岗位编码'))
    description = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('岗位描述'))
    status = models.IntegerField(choices=STATUS_CHOICES, default=1, verbose_name=_('岗位状态'))
    sort = models.IntegerField(default=1, verbose_name=_('排序'))
    # user = models.ManyToManyField(User, related_name='posts', verbose_name=_('用户'), db_constraint=False)
    history = HistoricalRecords(verbose_name=_("历史修改记录"))

    def __str__(self):
        return self.name

    class Meta:
        db_table = f'{table_prefix}_post'
        verbose_name = _('岗位管理')
        verbose_name_plural = verbose_name
        ordering = ['-id']


class Dept(MP_Node, BaseModel):
    """
    部门表
    """
    name = models.CharField(max_length=64, verbose_name=_('部门名称'))
    key = models.CharField(max_length=64, unique=True, null=True, blank=True, verbose_name=_('部门标识'))
    sort = models.IntegerField(default=1, verbose_name=_('排序'))
    owner = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('负责人'))
    phone = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('联系电话'))
    email = models.EmailField(max_length=64, null=True, blank=True, verbose_name=_('邮箱'))
    status = models.BooleanField(default=True, verbose_name=_('部门状态'))
    # user = models.ManyToManyField(User, null=True, blank=True, related_name='depts', verbose_name=_('用户'),
    #                               db_constraint=False)
    history = HistoricalRecords(verbose_name=_("历史修改记录"))
    # parent = models.ForeignKey(
    #     to="self",
    #     on_delete=models.CASCADE,
    #     default=None,
    #     verbose_name="上级部门",
    #     db_constraint=False,
    #     null=True,
    #     blank=True,
    #     help_text="上级部门",
    # )
    node_order_by = ["sort"]

    @classmethod
    def recursion_all_dept(cls, dept_id: int, dept_all_list=None, dept_list=None):
        """
        递归获取部门的所有下级部门
        :param dept_id: 需要获取的id
        :param dept_all_list: 所有列表
        :param dept_list: 递归list
        :return:
        """
        if not dept_all_list:
            dept_all_list = Dept.objects.values("id", "parent")
        if dept_list is None:
            dept_list = [dept_id]
        for ele in dept_all_list:
            if ele.get("parent") == dept_id:
                dept_list.append(ele.get("id"))
                cls.recursion_all_dept(ele.get("id"), dept_all_list, dept_list)
        return list(set(dept_list))

    def __str__(self):
        return self.name

    class Meta:
        db_table = f'{table_prefix}_dept'
        verbose_name = _('部门管理')
        verbose_name_plural = verbose_name
        # ordering = ['-id']


class Menu(MP_Node, BaseModel):
    """
    展示菜单表【前端展示的菜单和层级列表】
    """
    ISLINK_CHOICES = (
        (0, _('否')),
        (1, _('是')),
    )
    icon = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('图标'))
    name = models.CharField(max_length=64, verbose_name=_('菜单名称'))
    sort = models.IntegerField(default=1, verbose_name=_('菜单排序'))
    is_link = models.IntegerField(choices=ISLINK_CHOICES, default=0, verbose_name=_('是否外链'))
    link_url = models.CharField(max_length=65535, null=True, blank=True, verbose_name=_('外链地址'))
    is_catalog = models.BooleanField(default=False, verbose_name=_('是否目录'))
    web_path = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('前端路径'))
    component = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('组件路径'))
    component_name = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('组件名称'))
    status = models.BooleanField(default=True, verbose_name=_('菜单状态'))
    cache = models.BooleanField(default=False, verbose_name=_('是否缓存'))
    visible = models.BooleanField(default=True, verbose_name=_('侧边栏是否可见'))
    is_iframe = models.BooleanField(default=False, verbose_name=_('是否内嵌iframe'))
    is_affix = models.BooleanField(default=False, verbose_name=_('是否固定'))
    history = HistoricalRecords(verbose_name=_("历史修改记录"))
    # parent = models.ForeignKey(
    #     to="self",
    #     on_delete=models.CASCADE,
    #     verbose_name="上级菜单",
    #     null=True,
    #     blank=True,
    #     db_constraint=False,
    #     help_text="上级菜单",
    # )
    node_order_by = ["sort"]

    @classmethod
    def get_all_parent(cls, id: int, all_list=None, nodes=None):
        """
        递归获取给定ID的所有层级
        :param id: 参数ID
        :param all_list: 所有列表
        :param nodes: 递归列表
        :return: nodes
        """
        if not all_list:
            all_list = Menu.objects.values("id", "name", "parent")
        if nodes is None:
            nodes = []
        for ele in all_list:
            if ele.get("id") == id:
                parent_id = ele.get("parent")
                if parent_id is not None:
                    cls.get_all_parent(parent_id, all_list, nodes)
                nodes.append(ele)
        return nodes

    def __str__(self):
        return self.name

    class Meta:
        db_table = f'{table_prefix}_menu'
        verbose_name = _('菜单管理')
        verbose_name_plural = verbose_name
        # ordering = ['-id']


class MenuField(BaseModel):
    """
    展示菜单字段表[应该是前端展示用的]
    """
    model = models.CharField(max_length=64, verbose_name=_('表名'))
    menu = models.ForeignKey(Menu, on_delete=models.CASCADE, verbose_name=_('菜单'), db_constraint=False)
    field_name = models.CharField(max_length=64, verbose_name=_('模型表字段名'))
    title = models.CharField(max_length=64, verbose_name=_('字段显示名'))
    history = HistoricalRecords(verbose_name=_("历史修改记录"))

    def __str__(self):
        return f"{self.model}-{self.title}"

    class Meta:
        db_table = f'{table_prefix}_menu_field'
        verbose_name = _('菜单字段管理')
        verbose_name_plural = verbose_name
        ordering = ['-id']


class FieldPermission(BaseModel):
    """
    角色字段权限表
    """
    role = models.ForeignKey(Role, on_delete=models.CASCADE, verbose_name=_('角色'), db_constraint=False)
    field = models.ForeignKey(MenuField, on_delete=models.CASCADE, verbose_name=_('字段'), db_constraint=False)
    is_query = models.BooleanField(default=True, verbose_name=_('是否可查询'))
    is_create = models.BooleanField(default=True, verbose_name=_('是否可创建'))
    is_update = models.BooleanField(default=True, verbose_name=_('是否可修改'))
    history = HistoricalRecords(verbose_name=_("历史修改记录"))

    def __str__(self):
        return f"{self.role.name}-{self.field.model}-{self.field.title}"


class MenuButton(BaseModel):
    """
    菜单详细权限设置
    接口权限配置
    配置示例
    name:[查询, 详情， 新增， 编辑， 删除]
    value:【area:Search, area:Retrieve, area:Create, area:Update, area:Delete】
    api：【/api/mrbac/area/, /api/mrbac/area/{id}/, /api/mrbac/area/, /api/mrbac/area/{id}/, /api/mrbac/area/{id}/】
    method:【GET, GET, POST, PUT, DELETE】
    """
    METHOD_CHOICES = (
        (0, _('GET')),
        (1, _('POST')),
        (2, _('PUT')),
        (3, _('DELETE')),
    )
    menu = models.ForeignKey(Menu, on_delete=models.CASCADE, verbose_name=_('菜单'), related_name='menu_permission',
                             db_constraint=False)
    name = models.CharField(max_length=255, verbose_name=_('权限名称'))
    value = models.CharField(unique=True, max_length=255, verbose_name=_('权限值'))
    api = models.CharField(max_length=255, verbose_name=_('接口地址'))
    method = models.IntegerField(choices=METHOD_CHOICES, verbose_name=_('请求方式'))
    history = HistoricalRecords(verbose_name=_("历史修改记录"))

    def __str__(self):
        return f"{self.name}-{self.value}"

    class Meta:
        db_table = f'{table_prefix}_menu_permission'
        verbose_name = _('菜单权限')
        verbose_name_plural = verbose_name
        ordering = ['-id']


class RoleMenuPermission(BaseModel):
    """
    角色菜单对应表【页面展示权限】
    """
    role = models.ForeignKey(Role, on_delete=models.CASCADE, verbose_name=_('角色'),
                             related_name='role_menu_permission', db_constraint=False)
    menu = models.ForeignKey(Menu, on_delete=models.CASCADE, verbose_name=_('菜单权限'), null=True, blank=True,
                             related_name='role_menu_permission', db_constraint=False)
    history = HistoricalRecords(verbose_name=_("历史修改记录"))

    def __str__(self):
        return f"{self.role.name if self.role else None}-{self.menu.name if self.menu else None}"

    class Meta:
        db_table = f'{table_prefix}_role_menu_permission'
        verbose_name = _('角色菜单权限')
        verbose_name_plural = verbose_name
        ordering = ['-id']


class RoleMenuButtonPermission(BaseModel):
    """
    角色菜单权限表
    角色接口权限表
    使用逻辑在.utils.data_level_permission_filter.py中
    """
    DATASCOPE_CHOICES = (
        (0, _('仅本人数据权限')),
        (1, _('本部门及以下数据权限')),
        (2, _('本部门数据权限')),
        (3, _('全部数据权限')),
        (4, _('自定数据权限')),
    )
    role = models.ForeignKey(Role, on_delete=models.CASCADE, verbose_name=_('角色'),
                             related_name='role_menu_button_permission', db_constraint=False)
    menu_button = models.ForeignKey(MenuButton, on_delete=models.CASCADE, verbose_name=_('菜单按钮权限'), null=True,
                                    blank=True, related_name='role_menu_button_permission', db_constraint=False)
    data_range = models.IntegerField(choices=DATASCOPE_CHOICES, verbose_name=_('数据权限范围'), default=0)
    dept = models.ManyToManyField(Dept, verbose_name=_('数据权限部门'), blank=True, null=True, db_constraint=False)
    history = HistoricalRecords(verbose_name=_("历史修改记录"))

    def __str__(self):
        return f"{self.role.name}-{self.menu_button.name if self.menu_button else None}-{self.menu_button.value if self.menu_button else None}"

    class Meta:
        db_table = f'{table_prefix}_role_menu_button_permission'
        verbose_name = _('角色菜单按钮权限')
        verbose_name_plural = verbose_name
        ordering = ['-id']


class Dictionary(MP_Node, BaseModel):
    """
    字典表
    """
    TYPE_CHOICES = (
        (0, "text"),
        (1, "number"),
        (2, "date"),
        (3, "datetime"),
        (4, "time"),
        (5, "files"),
        (6, "boolean"),
        (7, "images"),
    )
    label = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('字典名称'))
    value = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('字典编码'))
    type = models.IntegerField(choices=TYPE_CHOICES, verbose_name=_('字典类型'), default=0)
    color = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('颜色'))
    is_value = models.BooleanField(default=False, verbose_name=_('是否为value值'),
                                   help_text=_('是否为value值，用来做具体值存放'))
    status = models.BooleanField(default=True, verbose_name=_('是否启用'))
    sort = models.IntegerField(default=1, verbose_name=_('排序'))
    remark = models.CharField(max_length=65535, null=True, blank=True, verbose_name=_('备注'))
    history = HistoricalRecords(verbose_name=_("历史修改记录"))

    def __str__(self):
        return f"{self.label}-{self.value}"

    class Meta:
        db_table = f'{table_prefix}_dictionary'
        verbose_name = _('字典管理')
        verbose_name_plural = verbose_name
        ordering = ['-id']

    # def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
    #     super().save(force_insert, force_update, using, update_fields)
    #     dispatch.refresh_dictionary()  # 有更新则刷新字典配置
    #
    # def delete(self, using=None, keep_parents=False):
    #     res = super().delete(using, keep_parents)
    #     dispatch.refresh_dictionary()
    #     return res


class Area(MP_Node, BaseModel):
    """
    地区表
    """
    LEVEL_CHOICES = (
        (1, _('省份')),
        (2, _('城市')),
        (3, _('区县')),
        (4, _('乡镇')),
    )
    name = models.CharField(max_length=255, verbose_name=_('地区名称'))
    code = models.CharField(max_length=255, verbose_name=_('地区编码'), unique=True)
    level = models.BigIntegerField(choices=LEVEL_CHOICES, default=4, verbose_name=_('地区层级'))
    pinyin = models.CharField(max_length=255, verbose_name=_('拼音'))
    initials = models.CharField(max_length=255, verbose_name=_('首字母'))
    status = models.BooleanField(default=True, verbose_name=_('是否启用'))
    # p_code = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, verbose_name=_('上级地区'),
    #                            to_field='code')

    history = HistoricalRecords(verbose_name=_("历史修改记录"))
    node_order_by = ['code']

    def __str__(self):
        return self.name

    class Meta:
        db_table = f'{table_prefix}_area'
        verbose_name = _('地区管理')
        verbose_name_plural = verbose_name
        # ordering = ['-id']


class ApiWhiteList(BaseModel):
    """
    API白名单
    """
    METHOD_CHOICES = (
        (0, "GET"),
        (1, "POST"),
        (2, "PUT"),
        (3, "DELETE"),
    )
    url = models.CharField(max_length=255, verbose_name=_('URL'))
    method = models.IntegerField(choices=METHOD_CHOICES, verbose_name=_('请求方式'), null=True, blank=True)
    enable_datasource = models.BooleanField(default=True, verbose_name=_('激活数据权限'))
    history = HistoricalRecords(verbose_name=_("历史修改记录"))

    def __str__(self):
        return f"{self.url}-{self.method}"

    class Meta:
        db_table = f'{table_prefix}_api_white_list'
        verbose_name = _('接口白名单')
        verbose_name_plural = verbose_name
        ordering = ['-id']


class SystemConfig(MP_Node, BaseModel):
    """
    系统配置表
    """
    FORM_ITEM_TYPE_LIST = (
        (0, "text"),
        (1, "datetime"),
        (2, "date"),
        (3, "textarea"),
        (4, "select"),
        (5, "checkbox"),
        (6, "radio"),
        (7, "img"),
        (8, "file"),
        (9, "switch"),
        (10, "number"),
        (11, "array"),
        (12, "images"),
        (13, "foreignkey"),
        (14, "manytomany"),
        (15, "time"),
    )
    title = models.CharField(max_length=255, verbose_name=_('标题'))
    key = models.CharField(max_length=255, verbose_name=_('键'))
    value = models.CharField(max_length=255, verbose_name=_('值'), null=True, blank=True)
    sort = models.IntegerField(default=1, verbose_name=_('排序'))
    status = models.BooleanField(default=True, verbose_name=_('是否启用'))
    data_options = models.JSONField(null=True, blank=True, verbose_name=_('数据选项'))
    form_item_type = models.IntegerField(choices=FORM_ITEM_TYPE_LIST, verbose_name=_('表单类型'), default=0)
    rule = models.JSONField(null=True, blank=True, verbose_name=_('表单验证规则'))
    placeholder = models.CharField(max_length=255, verbose_name=_('表单提示'), null=True, blank=True)
    setting = models.JSONField(null=True, blank=True, verbose_name=_('表单配置'))
    history = HistoricalRecords(verbose_name=_("历史修改记录"))

    # def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
    #     super().save(force_insert, force_update, using, update_fields)
    #     dispatch.refresh_system_config()  # 有更新则刷新系统配置
    #
    # def delete(self, using=None, keep_parents=False):
    #     res = super().delete(using, keep_parents)
    #     dispatch.refresh_system_config()
    #     return res

    def __str__(self):
        return f"{self.title}-{self.key}"

    class Meta:
        db_table = f'{table_prefix}_system_config'
        verbose_name = _('系统配置')
        verbose_name_plural = verbose_name
        ordering = ['-id']
